<script setup>
import { ref, watch, onMounted, computed, onBeforeUnmount, nextTick } from 'vue';
import { Icon } from '@iconify/vue';
import { useI18n } from 'vue-i18n';
import { storeToRefs } from 'pinia';
import { useWorkspaceStore } from '../../stores/workspace';
import TreeView from '../../components/TreeView.vue';
import SearchSidebar from './SearchSidebar.vue';
import TimelineView from '../../components/TimelineView.vue'
import AiTimelinePanel from '../../components/AiTimelinePanel.vue'
import ExtensionsSidebar from './ExtensionsSidebar.vue'

import { useTimelineStore } from '../../stores/timeline'
import { commandService } from '../../services/commandService'

const props = defineProps({
  title: { type: String, default: 'Explorer' },
  items: { type: Array, default: () => [] }, // [{ id, label }]
  show: { type: Boolean, default: true },
  width: { type: Number, default: 240 },
});
const emit = defineEmits(['select', 'update:width']);
const { t } = useI18n();

const workspaceStore = useWorkspaceStore();
const { workspaceRoot, workspaceRefreshTick } = storeToRefs(workspaceStore);

function onSelect(item) {
  emit('select', item);
}
const treeRootChildren = ref([]);
const isRehydrating = ref(false);
const isRefreshing = ref(false);
let refreshQueued = false;
let refreshTimer = null;

async function refresh() {
  if (!workspaceRoot.value) { treeRootChildren.value = []; return; }
  // 使用缓存优先，首次或失效时自动回源
  treeRootChildren.value = await workspaceStore.getCachedChildren(workspaceRoot.value);
  await nextTick();
  try {
    if (tree.value?.rehydrateExpanded) {
      isRehydrating.value = true;
      await tree.value.rehydrateExpanded();
    }
  } catch {} finally { isRehydrating.value = false; }
}

async function scheduleRefresh() {
  refreshQueued = true;
  if (isRefreshing.value) return;
  while (refreshQueued) {
    refreshQueued = false;
    isRefreshing.value = true;
    try { await refresh(); }
    finally { isRefreshing.value = false; }
  }
}

function scheduleRefreshDebounced(delay = 120) {
  if (refreshTimer) { try { clearTimeout(refreshTimer); } catch {} }
  refreshTimer = setTimeout(() => {
    refreshTimer = null;
    void scheduleRefresh();
  }, delay);
}

// 暴露给父组件用于主动刷新（删除等操作的兜底）
function refreshPublic() { return scheduleRefresh(); }
async function loadChildrenFn(node) {
  const base = String(node.id || node.path || '');
  
  try {
    if (isRehydrating.value) {
      // 重新水化时强制重新加载
      return await workspaceStore.reloadChildren(base);
    } else {
      // 正常加载时使用getCachedChildren，它会自动尝试索引、缓存和文件系统
      return await workspaceStore.getCachedChildren(base);
    }
  } catch (error) {
    console.warn('Failed to load children for node:', base, error);
    // 加载失败时返回空数组
    return [];
  }
}

// fs-change 增量刷新侦听（由 WorkspaceService 透传）
function onFsChange(e) {
  try {
    const detail = e?.detail || {};
    const type = String(detail.event_type || '');
    const path = String(detail.path || '');
    const oldPath = detail.old_path ? String(detail.old_path) : undefined;
    if (!type || !path) return;
    // 更新缓存失效
    workspaceStore.applyFileChange(type, path, oldPath);
    // 合并+防抖刷新，避免闪动
    scheduleRefreshDebounced();
  } catch {}
}

// refresh when root changes or tick updates
watch(workspaceRoot, () => { scheduleRefreshDebounced(); });
watch(workspaceRefreshTick, () => { scheduleRefreshDebounced(); });

onMounted(() => {
  // 首次直接刷新一次，随后事件由合并+防抖控制
  void scheduleRefresh();
  try { window.addEventListener('fs-change', onFsChange); } catch {}
});
onBeforeUnmount(() => {
  try { window.removeEventListener('fs-change', onFsChange); } catch {}
});

const rootNode = computed(() => {
  const root = workspaceRoot.value;
  if (!root) return null;
  const name = root.split(/[\\/]/).pop() || root;
  return { id: root, label: name, isDir: true, children: treeRootChildren.value };
});

// sidebar mode: explorer | search | timeline | ai-timeline | extensions
const mode = ref('explorer');
const searchText = ref('');
const activeUri = ref('');
const tl = useTimelineStore();

// Collapsible sections state
const explorerCollapsed = ref(false);
const timelineCollapsed = ref(false);

// Expose TreeView controls to parent (AppShell)
const tree = ref(null);
function beginNewFileInline(node) {
  try { tree.value?.beginInline?.('new-file', node ?? rootNode.value); } catch {}
}
function beginNewFolderInline(node) {
  try { tree.value?.beginInline?.('new-folder', node ?? rootNode.value); } catch {}
}
function beginRenameInline(node) {
  try { tree.value?.beginInline?.('rename', node ?? rootNode.value); } catch {}
}

defineExpose({ beginNewFileInline, beginNewFolderInline, beginRenameInline, refresh: refreshPublic });

// When user selects a node in explorer, remember it to show its timeline when switching to timeline mode
function handleSelectForTimeline(node) {
  const p = String(node?.id || node?.path || '');
  if (p) activeUri.value = p;
}
const dragging = ref(false);
let dragStartX = 0;
let dragStartW = 0;

function onHandleDown(e) {
  if (!props.show) return;
  dragging.value = true;
  dragStartX = e.clientX;
  dragStartW = props.width;
  document.body.style.cursor = 'col-resize';
  document.body.style.userSelect = 'none';
  window.addEventListener('mousemove', onHandleMove, { passive: true });
  window.addEventListener('mouseup', onHandleUp);
}
function onHandleMove(e) {
  const dx = e.clientX - dragStartX;
  let next = dragStartW + dx; // dragging right increases width
  if (next < 0) next = 0;
  if (next > 720) next = 720;
  emit('update:width', next);
}
function onHandleUp() {
  dragging.value = false;
  document.body.style.cursor = '';
  document.body.style.userSelect = '';
  window.removeEventListener('mousemove', onHandleMove);
  window.removeEventListener('mouseup', onHandleUp);
}

// AI时间线事件处理
function handleAiTimelineItemClick(entry) {
  console.log('AI Timeline item clicked:', entry);
  // 打开文件并切换到该文件
  if (entry.path) {
    activeUri.value = entry.path;
    emit('select', entry.path, { preview: false });
  }
}

function handleAcceptChange(entry) {
  console.log('Accept AI change:', entry);
  // 这里可以添加接受变更的逻辑
}

function handleRejectChange(entry) {
  console.log('Reject AI change:', entry);
  // 这里可以添加拒绝变更的逻辑
}
</script>

<template>
  <aside
    class="relative flex h-full min-h-0 flex-col overflow-hidden bg-panel-bg/60 border-r border-panel-border"
    :class="dragging ? '' : 'transition-[width] duration-200 ease-in-out'"
    :style="{ width: (props.show ? props.width : 0) + 'px', minWidth: '0px' }"
  >
    <!-- Left vertical toolbar (Activity Bar style) -->
    <div class="absolute left-0 top-0 bottom-0 w-8 border-r border-panel-border flex flex-col items-center py-1 gap-1">
      <button
        class="h-7 w-7 inline-flex items-center justify-center rounded hover:bg-app-bg"
        :class="mode==='explorer' ? 'text-accent' : 'text-muted-fg'"
        @click="mode='explorer'"
        :title="t ? (t('menu.explorer') || 'Explorer') : 'Explorer'"
        aria-label="Explorer"
      >
        <Icon icon="codicon:files" width="16" height="16" />
      </button>
      <button
        class="h-7 w-7 inline-flex items-center justify-center rounded hover:bg-app-bg"
        :class="mode==='search' ? 'text-accent' : 'text-muted-fg'"
        @click="mode='search'"
        :title="t ? (t('menu.search') || 'Search') : 'Search'"
        aria-label="Search"
      >
        <Icon icon="codicon:search" width="16" height="16" />
      </button>
      <button
        class="h-7 w-7 inline-flex items-center justify-center rounded hover:bg-app-bg"
        :class="mode==='timeline' ? 'text-accent' : 'text-muted-fg'"
        @click="mode='timeline'"
        title="Timeline"
        aria-label="Timeline"
      >
        <Icon icon="codicon:timeline" width="16" height="16" />
      </button>
      <button
        class="h-7 w-7 inline-flex items-center justify-center rounded hover:bg-app-bg"
        :class="mode==='ai-timeline' ? 'text-accent' : 'text-muted-fg'"
        @click="mode='ai-timeline'"
        title="AI Timeline"
        aria-label="AI Timeline"
      >
        <Icon icon="codicon:robot" width="16" height="16" />
      </button>

      <!-- New: Extensions -->
      <button
        class="h-7 w-7 inline-flex items-center justify-center rounded hover:bg-app-bg"
        :class="mode==='extensions' ? 'text-accent' : 'text-muted-fg'"
        @click="mode='extensions'"
        :title="t ? (t('menu.extensions') || 'Extensions') : 'Extensions'"
        aria-label="Extensions"
      >
        <Icon icon="codicon:extensions" width="16" height="16" />
      </button>
    </div>

    <!-- Main content area -->
    <div class="absolute bottom-0 top-0 right-0 left-8 flex flex-col text-sm overflow-hidden" data-explorer-root="1">
      <!-- Explorer Mode -->
      <template v-if="mode === 'explorer' && workspaceRoot">
        <!-- Main title for Explorer -->
        <div class="flex items-center px-2 py-2 bg-panel-bg/80 border-b border-panel-border">
          <div class="text-xs font-medium text-muted-strong">
            {{ t('menu.explorer') }}
          </div>
        </div>
        <div class="flex-1 flex flex-col min-h-0">
          <!-- Explorer Section -->
          <div class="flex-1 flex flex-col min-h-0">
            <!-- Folder Header (collapsible) -->
            <div class="flex items-center justify-between px-2 py-1 bg-panel-bg/30">
              <button 
                class="flex items-center gap-1 text-xs font-medium text-muted-strong hover:text-app-fg"
                @click="explorerCollapsed = !explorerCollapsed"
              >
                <Icon 
                  :icon="explorerCollapsed ? 'codicon:chevron-right' : 'codicon:chevron-down'" 
                  width="12" 
                  height="12" 
                  class="transition-transform duration-150"
                />
                {{ t('sidebar.folder') }}
              </button>
            </div>
            <!-- Explorer Content -->
            <div v-if="!explorerCollapsed" class="flex-1 min-h-0 overflow-hidden">
              <div class="h-full overflow-auto p-1 thin-scrollbar scrollbar-compact">
                <TreeView
                  ref="tree"
                  v-if="rootNode"
                  :root="rootNode"
                  :showRoot="true"
                  :indent="8"
                  :compressFolders="!isRehydrating"
                  :animateChanges="!isRehydrating"
                  :loadChildren="loadChildrenFn"
                  :getIcon="(n)=> (n && (n.isDir===true||n.is_dir===true||n.isFolder===true)) ? () => '' : null"
                  @open="(node)=> { $emit('select', node?.id || node?.path, { preview: false }); handleSelectForTimeline(node); }"
                  @preview="(node)=> { $emit('select', node?.id || node?.path, { preview: false }); handleSelectForTimeline(node); }"
                />
              </div>
            </div>
          </div>

          <!-- Timeline Section -->
          <div class="flex-shrink-0 flex flex-col min-h-0">
            <!-- Timeline Header (collapsible) -->
            <div class="flex items-center justify-between px-2 py-1 bg-panel-bg/80">
              <button 
                class="flex items-center gap-1 text-xs font-medium text-muted-strong hover:text-app-fg"
                @click="timelineCollapsed = !timelineCollapsed"
              >
                <Icon 
                  :icon="timelineCollapsed ? 'codicon:chevron-right' : 'codicon:chevron-down'" 
                  width="12" 
                  height="12" 
                  class="transition-transform duration-150"
                />
                {{ t('sidebar.timeline') }}
              </button>
            </div>
            <!-- Timeline Content -->
            <div v-if="!timelineCollapsed" class="flex-1 min-h-0 max-h-64 overflow-hidden">
              <div class="h-full overflow-auto thin-scrollbar scrollbar-compact">
                <TimelineView :uri="activeUri" />
              </div>
            </div>
          </div>
        </div>
      </template>

      <!-- Search Mode -->
      <template v-else-if="mode === 'search' && workspaceRoot">
        <SearchSidebar @open-file="(p) => $emit('select', p, { preview: false })" />
      </template>

      <!-- Timeline Mode -->
      <template v-else-if="mode === 'timeline' && workspaceRoot">
        <TimelineView :uri="activeUri" />
      </template>

      <!-- AI Timeline Mode -->
      <template v-else-if="mode === 'ai-timeline'">
        <AiTimelinePanel
          :active-file-path="activeUri"
          :show-all-files="true"
          @timeline-item-click="handleAiTimelineItemClick"
          @accept-change="handleAcceptChange"
          @reject-change="handleRejectChange"
        />
      </template>

      <!-- Extensions Mode -->
      <template v-else-if="mode === 'extensions'">
        <ExtensionsSidebar />
      </template>
    </div>
    
    <!-- drag handle on the right edge -->
    <div class="absolute right-0 top-0 h-full w-1 cursor-col-resize hover:bg-purple-500/60" @mousedown="onHandleDown"></div>
    <!-- Drag handle: 1px visible line + enlarged invisible hit area -->
    <div class="absolute right-0 top-0 h-full w-3 z-10 group">
      <!-- visible 1px line for hover/active highlight -->
      <div class="absolute right-0 top-0 h-full w-px bg-transparent pointer-events-none group-hover:bg-purple-500/60"></div>
      <!-- invisible hit area capturing drag -->
      <div class="absolute inset-0 cursor-col-resize touch-none" @mousedown="onHandleDown"></div>
    </div>
  </aside>
</template>


